package org.liveboardgames.agricola.control.delegates.action
{
    import com.adobe.cairngorm.control.CairngormEventDispatcher;
    
    import org.liveboardgames.agricola.control.delegates.helper.GameHelper;
    import org.liveboardgames.agricola.control.events.ActionCompleteEvent;
    import org.liveboardgames.agricola.control.events.PerformActionEvent;
    import org.liveboardgames.agricola.model.AgricolaModelLocator;
    import org.liveboardgames.agricola.model.PopupModel;
    import org.liveboardgames.agricola.vo.Game;
    import org.liveboardgames.agricola.vo.action.Action;
    import org.liveboardgames.agricola.vo.card.Card;
    import org.liveboardgames.agricola.vo.common.Target;
    import org.liveboardgames.agricola.vo.player.Player;
    
    import mx.collections.ArrayCollection;
    import mx.collections.ListCollectionView;
    import mx.events.CollectionEvent;
    
    public class AgricolaActionController
    {
        public var player:Player;
        
        private var _game:Game;
        
        private var _card:Card;
        
        private var _remainingActions:ListCollectionView;
        
        private var _playedActions:ListCollectionView;
        
        private var _exclusiveActions:ListCollectionView;
        
        private var _playableActions:ListCollectionView;
        
        public function AgricolaActionController(game:Game)
        {
            this._game = game;
        }
        
        public function addNewPlayedAction(action:Action):void
        {
            // Remove any popup that may have been displayed
            AgricolaModelLocator.getInstance().popups.currentActionPopupIndex = PopupModel.POPUP_NO_ACTION_INDEX;
            
            var actionIndex:int = this._remainingActions.getItemIndex(action);
            this._remainingActions.removeItemAt(actionIndex);
            this._playedActions.addItem(action);
        }
        
        public function addNewActionsInQueue(actions:ListCollectionView, target:Target = null):void
        {
            // Remove any popup that may have been displayed
            AgricolaModelLocator.getInstance().popups.currentActionPopupIndex = PopupModel.POPUP_NO_ACTION_INDEX;
            
            if (actions != null && actions.length > 0)
            {
                for each (var action:Action in actions)
                {
                    if (target != null)
                    {
                        action.target = target;
                    }
                    this._remainingActions.addItem(action);
                }
                onPlayedActionsChange();
            }
        }
        
        public function setCard(card:Card, actions:ListCollectionView = null):void
        {
            this.card = card;
            if (actions != null)
            {
                this.actions = actions;
            }
        }
        
        public function set card(card:Card):void
        {
            if (card != null)
            {
                this.actions = card.actions;
                this._card = card;
                this._exclusiveActions = card.exclusiveActions;
            }
        }
        
        public function set actions(actions:ListCollectionView):void
        {
            //this._card = null;
            //this._exclusiveActions = null;
            this._remainingActions = actions;
            this._playedActions = new ArrayCollection();
            this._playedActions.addEventListener(CollectionEvent.COLLECTION_CHANGE, onPlayedActionsChange);
        }
        
        private function onPlayedActionsChange(event:CollectionEvent = null):void
        {
            // First get all the actions that are actually playable
            _playableActions = GameHelper.getPlayableActions(_remainingActions, player, _playedActions, _exclusiveActions);
            
            // TODO: If there is no more playable actions, notify that all actions have been 
            // played, so that the interface can allow the player to do something else, like 
            // finish their turn
            if (_playableActions == null || _playableActions.length == 0)
            {
                trace("TODO: Notifying game that no more action is pending");
                var actionFinishedEvent:ActionCompleteEvent = new ActionCompleteEvent(ActionCompleteEvent.ACTION_COMPLETE);
                actionFinishedEvent.game = AgricolaModelLocator.getInstance().game;
                CairngormEventDispatcher.getInstance().dispatchEvent(actionFinishedEvent);
                //AgricolaModelLocator.getInstance().workflowState = AgricolaModelLocator.ACTION_PLAYED_STATE;
                return;
            }
            
            // Now get all the automatic actions that can be accomplished without any user input
            var automaticActions:ListCollectionView = GameHelper.getAutomaticActions(_playableActions);
            
            // Automatically play the first one of them if there are any
            // The PerformActionCommand should then update the list of played actions of the controller
            if (automaticActions != null && automaticActions.length > 0)
            {
                dispatchActionEvent(automaticActions.getItemAt(0) as Action, player);
            }
            // Otherwise, need to offer the player the possibility to play a manual action. 
            // At this point, all playable actions are manual actions 
            else if (_playableActions.length == 1)
            {
                dispatchActionEvent(_playableActions.getItemAt(0) as Action, player);
            }
            // Several actions are possible, the player needs to be offered the choice between them
            else
            {
                AgricolaModelLocator.getInstance().popups.currentActionPopupIndex = PopupModel.POPUP_CHOOSE_ACTION_INDEX;
                AgricolaModelLocator.getInstance().popups.possibleActions = _playableActions;
            }
        
        }
        
        public function executeAllActions():void
        {
            if ((this._card == null || this.player == null) && (this._remainingActions == null))
            {
                throw new Error("The AgricolaActionController executeAllActionsForCard needs that a card and a player be " +
                    "set in the AgricolaActionController");
            }
            // Initialize the action play
            onPlayedActionsChange(new CollectionEvent(CollectionEvent.COLLECTION_CHANGE));
        }
        
        public function dispatchActionEvent(action:Action, player:Player):void
        {
            var performActionEvent:PerformActionEvent = new PerformActionEvent(PerformActionEvent.PERFORM_ACTION);
            performActionEvent.action = action;
            performActionEvent.game = _game;
            performActionEvent.actionTarget = player;
            CairngormEventDispatcher.getInstance().dispatchEvent(performActionEvent);
        }
    }
}